package com.example.service.medical;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import com.example.common.Constants;
import com.example.common.enums.ResultCodeEnum;
import com.example.common.enums.RoleEnum;
import com.example.common.enums.RoleStatusEnum;
import com.example.exception.CustomException;
import com.example.mapper.appointment.ReservationMapper;
import com.example.mapper.medical.DoctorMapper;
import com.example.mapper.medical.HospitalMapper;
import com.example.model.dto.AccountDto;
import com.example.model.dto.HospitalDto;
import com.example.model.entity.medical.Doctor;
import com.example.model.entity.medical.Hospital;
import com.example.model.entity.other.Account;
import com.example.model.vo.HospitalVO;
import com.example.utils.TokenUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 医院表业务处理
 **/
@Service
public class HospitalService {

    @Resource
    private HospitalMapper hospitalMapper;
    @Resource
    private DoctorMapper doctorMapper;
    @Resource
    private ReservationMapper reservationMapper;


    /**
     * 查询挂号量靠前的医院
     *
     * @return
     */
    public List<HospitalVO> selectTopHospitals() {
        List<HospitalVO> hospitalVOList = new ArrayList<>();
        List<Hospital> hospitalList = hospitalMapper.selectAll(new Hospital());
        if (hospitalList == null || hospitalList.isEmpty()) {
            return new ArrayList<>();
        }
        hospitalList.stream().forEach(hospital -> {
            HospitalVO hospitalVO = new HospitalVO();
            Integer hospitalId = hospital.getId();
            List<Doctor> doctorList = doctorMapper.selectByHospitalId(hospitalId);
            AtomicLong hospitalCount = new AtomicLong(0L);
            doctorList.stream().forEach(doctor -> {
                Integer count = doctor.getCount();
                hospitalCount.addAndGet(count);
            });
            BeanUtils.copyProperties(hospital, hospitalVO);
            hospitalVO.setCount(hospitalCount.intValue());
            hospitalVO.setIds(doctorList.stream().map(Doctor::getId).collect(Collectors.toList()));
            hospitalVOList.add(hospitalVO);
        });
        hospitalVOList.sort(new Comparator<HospitalVO>() {
            @Override
            public int compare(HospitalVO o1, HospitalVO o2) {
                return o2.getCount() - o1.getCount();
            }
        });
        return hospitalVOList;
    }

    /**
     * 新增
     */
    public void add(Hospital hospital) {
        Hospital dbHospital = hospitalMapper.selectByUsername(hospital.getUsername());
        if (ObjectUtil.isNotNull(dbHospital)) {
            throw new CustomException(ResultCodeEnum.USER_EXIST_ERROR);
        }
        Account currentUser = TokenUtils.getCurrentUser();
        if (RoleEnum.ADMIN.name().equals(currentUser.getRole())) {
            if (ObjectUtil.isEmpty(hospital.getPassword())) {
                hospital.setPassword(Constants.HOSPITAL_DEFAULT_PASSWORD);
            }
            hospital.setRole(RoleEnum.HOSPITAL.name());
            hospital.setStatus(RoleStatusEnum.STATUS_OK.getName());
            hospitalMapper.insert(hospital);
        }
    }

    /**
     * 删除
     */
    public void deleteById(Integer id) {
        hospitalMapper.deleteById(id);
    }

    /**
     * 批量删除
     */
    public void deleteBatch(List<Integer> ids) {
        for (Integer id : ids) {
            hospitalMapper.deleteById(id);
        }
    }

    /**
     * 修改
     */
    public void updateById(Hospital Hospital) {
        hospitalMapper.updateById(Hospital);
    }

    /**
     * 根据ID查询
     */
    public Hospital selectById(Integer id) {
        return hospitalMapper.selectById(id);
    }

    /**
     * 查询所有
     */
    public List<Hospital> selectAll(Hospital Hospital) {
        Account currentUser = TokenUtils.getCurrentUser();
        if (RoleEnum.HOSPITAL.name().equals(currentUser.getRole())) {
            Hospital.setId(currentUser.getId());
        }
        return hospitalMapper.selectAll(Hospital);
    }

    /**
     * 分页查询
     */
    public PageInfo<Hospital> selectPage(Hospital Hospital, Integer pageNum, Integer pageSize) {
        Account currentUser = TokenUtils.getCurrentUser();
        if (RoleEnum.HOSPITAL.name().equals(currentUser.getRole())) {
            Hospital.setId(currentUser.getId());
        }
        PageHelper.startPage(pageNum, pageSize);
        List<Hospital> list = hospitalMapper.selectAll(Hospital);
        return PageInfo.of(list);
    }


    public void updateBatch(HospitalDto hospitalDto) {
        for (Integer id : hospitalDto.getIds()) {
            String status = hospitalDto.getStatus();
            Hospital hospital = hospitalMapper.selectById(id);
            hospital.setStatus(status);
            hospitalMapper.updateById(hospital);
        }
    }

    /**
     * 登录
     */
    public Account login(AccountDto accountDto) {
        Account dbHospital = hospitalMapper.selectByUsername(accountDto.getUsername());
        if (ObjectUtil.isNull(dbHospital)) {
            throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
        }
        if (!accountDto.getPassword().equals(dbHospital.getPassword())) {
            throw new CustomException(ResultCodeEnum.USER_ACCOUNT_ERROR);
        }
        // 生成token
        String tokenData = dbHospital.getId() + "-" + RoleEnum.HOSPITAL.name();
        String token = TokenUtils.createToken(tokenData, dbHospital.getPassword());
        dbHospital.setToken(token);
        return dbHospital;
    }


    /**
     * 修改密码
     */
    public void updatePassword(Account account) {
        Hospital dbHospital = hospitalMapper.selectByUsername(account.getUsername());
        if (ObjectUtil.isNull(dbHospital)) {
            throw new CustomException(ResultCodeEnum.USER_NOT_EXIST_ERROR);
        }
        if (!account.getPassword().equals(dbHospital.getPassword())) {
            throw new CustomException(ResultCodeEnum.PARAM_PASSWORD_ERROR);
        }
        dbHospital.setPassword(account.getNewPassword());
        hospitalMapper.updateById(dbHospital);
    }

    public List<Dict> selectBar() {
        // 获取当前用户信息，可能需要根据实际情况进行调整
        Account currentUser = TokenUtils.getCurrentUser();
        // 获取该医院医生及其预约数量
        List<Doctor> doctorsList = doctorMapper.selectByHospitalId(currentUser.getId()); // 获取所有医生
        // 按预约数量降序排序并取前10
        List<Doctor> topDoctors = doctorsList.stream()
                .sorted(Comparator.comparingInt(Doctor::getCount).reversed()) // 按照预约数量降序排序
                .limit(10) // 取前10名
                .collect(Collectors.toList());

        // 构建返回的数据格式
        List<Dict> dictList = new ArrayList<>();
        for (Doctor doctor : topDoctors) {
            String doctorName = doctor.getName();
            Integer count = doctor.getCount();

            Dict dict = Dict.create().set("name", doctorName).set("value", count);
            dictList.add(dict);
        }

        return dictList;
    }

    /**
     * 根据信息查询医院
     *
     * @param hospitalDto 医院信息
     * @return
     */
    public PageInfo<Hospital> selectHospitalByInfo(HospitalDto hospitalDto) {
        if (hospitalDto == null) {
            throw new CustomException(ResultCodeEnum.PARAM_ERROR);
        }
        PageHelper.startPage(hospitalDto.getPageNum(), hospitalDto.getPageSize());
        String city = hospitalDto.getCity();
        String level = hospitalDto.getLeave();
        List<Hospital> hospitalList = hospitalMapper.selectByInfo(city, level);
        // 根据医院挂号量排序返回
        Map<Integer, Integer> hospitalCountMap = new HashMap<>();
        hospitalList.stream().forEach(hospital -> {
            Integer hospitalId = hospital.getId();
            List<Doctor> doctorList = doctorMapper.selectByHospitalId(hospitalId);
            AtomicReference<Integer> hospitalCount = new AtomicReference<>(0);
            doctorList.stream().forEach(doctor -> {
                Integer count = doctor.getCount();
                hospitalCount.updateAndGet(v -> v + count);
            });
            if (hospitalCount.get() == null) {
                hospital.setCount(0);
            } else {
                hospital.setCount(hospitalCount.get());
            }
            hospitalCountMap.put(hospitalId, hospitalCount.get());
        });
        if (hospitalDto.getCountIsBoolean()==null) {
            return PageInfo.of(hospitalList);
        }
        hospitalList.sort(new Comparator<Hospital>() {
            @Override
            public int compare(Hospital o1, Hospital o2) {
                return hospitalCountMap.get(o2.getId()).intValue() - hospitalCountMap.get(o1.getId()).intValue();
            }
        });

        return PageInfo.of(hospitalList);
    }

    public List<Hospital> selectByCity(String city) {
        return hospitalMapper.selectByCity(city);
    }

    public Integer selectHospitalByName(String name) {
        return hospitalMapper.selectHospitalByName(name);
    }
}
